package com.suxin.utils;

import lombok.extern.slf4j.Slf4j;

import java.util.Optional;

/**
 * @author Tang
 * @classname ExceptionUtils
 * @description [ 消除 try,catch 的工具类 ]
 * @date 2023/1/9 15:37
 */
@Slf4j
public class ExceptionUtils {

    /**
     * 方法需要传一个参，没有返回值
     * ExceptionUtils.exceptionRun(Connection::setAutoCommit,connection,false);
     * @param consumer
     * @param bean
     * @param param
     * @param <T>
     * @param <R>
     */
    public static <T,R> void exceptionRun(ConsumerAccept<T,R> consumer,T bean, R param) {
        try {
            consumer.accept(bean,param);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法不需要传参，没有返回值
     * ExceptionUtils.exceptionRun(Connection::close,connection);
     * @param consumer
     * @param bean
     * @param <T>
     */
    public static <T> void exceptionRun(Consumer<T> consumer, T bean) {
        try {
            consumer.accept(bean);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法不需要传参，有返回值
     * Integer value = ExceptionUtils.exceptionReturn(Future::get, future);
     * @param function
     * @param bean
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T,R> Optional<R> exceptionReturn(Function<T,R> function, T bean) {
        try {
            return Optional.ofNullable(function.apply(bean));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Optional.empty();
    }


    /**
     * 方法需要一个参数，有返回值
     * List<Future<Integer>> futures = ExceptionUtils.exceptionReturn(AbstractExecutorService::invokeAll, executor, callables);
     * @param function
     * @param bean
     * @param param
     * @param <T>
     * @param <R>
     * @param <M>
     * @return
     */
    public static <T,R,M> Optional<R> exceptionReturn(FunctionApply<T,R,M> function, T bean,M param) {
        try {
            return Optional.ofNullable(function.apply(bean, param));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Optional.empty();
    }

    @FunctionalInterface
    public interface Function<T, R> {
        R apply(T t) throws Exception;
    }

    @FunctionalInterface
    public interface FunctionApply<T, R, M> {
        R apply(T t,M param) throws Exception;
    }

    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t) throws Exception;
    }

    @FunctionalInterface
    public interface ConsumerAccept<T, R> {
        void accept(T t, R r) throws Exception;
    }

}
